// 基座侧微应用主题桥：将主题DSL变量应用到各微应用容器
import { themeDSL, type ThemeDSL } from './themeDSL'

type AppName = string

class MicroThemeBridge {
  private static instance: MicroThemeBridge
  private appNameToContainer = new Map<AppName, HTMLElement>()
  private stopListen: (() => void) | null = null

  static getInstance(): MicroThemeBridge {
    if (!MicroThemeBridge.instance) {
      MicroThemeBridge.instance = new MicroThemeBridge()
    }
    return MicroThemeBridge.instance
  }

  // 注册微应用容器，基座在 beforeMount/afterMount 时调用
  register(appName: AppName, container: HTMLElement) {
    this.appNameToContainer.set(appName, container)
    // 初次注册时立即同步当前主题
    this.applyThemeToApp(appName, themeDSL.getAllVariables())
  }

  unregister(appName: AppName) {
    this.appNameToContainer.delete(appName)
  }

  // 启动监听：将 ThemeDSL 的变化应用到所有已注册微应用
  start() {
    if (this.stopListen) return
    const unsubscribe = themeDSL.addListener((dsl: ThemeDSL) => {
      this.applyThemeToAll(dsl)
    })
    this.stopListen = unsubscribe

    // 兼容 window.postMessage 的外部变更（例如其他页面广播）
    window.addEventListener('message', this.onMessage)
    // 首次启动时推送一次
    this.applyThemeToAll(themeDSL.getAllVariables())
  }

  stop() {
    if (this.stopListen) {
      this.stopListen()
      this.stopListen = null
    }
    window.removeEventListener('message', this.onMessage)
  }

  private onMessage = (event: MessageEvent) => {
    const data = event.data as any
    if (data && data.type === 'THEME_DSL_CHANGE' && data.dsl) {
      this.applyThemeToAll(data.dsl as ThemeDSL)
    }
  }

  private applyThemeToAll(dsl: ThemeDSL) {
    this.appNameToContainer.forEach((container, appName) => {
      this.applyThemeToApp(appName, dsl)
    })
  }

  private applyThemeToApp(appName: AppName, dsl: ThemeDSL) {
    const container = this.appNameToContainer.get(appName)
    if (!container) return

    // qiankun 在微应用根容器上会应用 data-qiankun="${name}" 属性
    // 在严格样式隔离模式下，需要确保CSS变量能够传递到shadow DOM中
    const targetEl = container.querySelector(`[data-qiankun="${appName}"]`) as HTMLElement || container

    // 在严格样式隔离模式下，需要将CSS变量应用到shadow root
    const shadowRoot = targetEl.shadowRoot
    if (shadowRoot) {
      // 如果有shadow root，通过CSS样式表设置变量
      let styleElement = shadowRoot.querySelector('#shadow-theme-vars') as HTMLStyleElement
      if (!styleElement) {
        styleElement = document.createElement('style')
        styleElement.id = 'shadow-theme-vars'
        shadowRoot.appendChild(styleElement)
      }
      
      const cssVars = Object.entries(dsl)
        .map(([key, value]) => `${key}: ${value};`)
        .join(' ')
      
      const mode = (dsl['--theme-mode'] as string) || 'light'
      styleElement.textContent = `:host { ${cssVars} color-scheme: ${mode}; }`
    } else {
      // 如果没有shadow root，应用到容器元素
      Object.entries(dsl).forEach(([key, value]) => {
        try {
          targetEl.style.setProperty(key, String(value))
        } catch {
          // ignore single variable failure
        }
      })
      
      // color-scheme 处理
      const mode = (dsl['--theme-mode'] as string) || 'light'
      targetEl.style.setProperty('color-scheme', mode === 'dark' ? 'dark' : 'light')
    }

    // 额外确保：在严格隔离模式下，通过CSS自定义属性传递主题变量
    // 这确保微应用能够访问到主题变量
    const cssVars = Object.entries(dsl)
      .map(([key, value]) => `${key}: ${value};`)
      .join(' ')
    
    // 创建一个style元素来确保变量传递
    let styleElement = container.querySelector('#micro-theme-vars') as HTMLStyleElement
    if (!styleElement) {
      styleElement = document.createElement('style')
      styleElement.id = 'micro-theme-vars'
      container.appendChild(styleElement)
    }
    
    styleElement.textContent = `:host { ${cssVars} }`
  }
}

export const microThemeBridge = MicroThemeBridge.getInstance()


